package com.twq.rules.rule2

/**
 * Created by tangweiqun on 2017/11/18.
 * 隐式作用域
 */
trait Group

object Group {

  implicit object StringMonoid extends Monoid[String] {

    def add(x: String, y: String): String = x concat y

    def unit: String = ""
  }

}

abstract class SemiGroup[A] extends Group {
  def add(x: A, y: A): A
}

object SemiGroup {

}

abstract class Monoid[A] extends SemiGroup[A] {
  def unit: A
}

object Monoid {

}

case class People(name: String, age: Int)

object People {
  implicit val peopleMonoid = new Monoid[People] {
    override def unit: People = People("", 0)

    override def add(x: People, y: People): People = People(x.name concat y.name, x.age + y.age)
  }
}

object Animals {

  case class Dog(name: String, age: Int)

  implicit val dogMonoid = new Monoid[Dog] {
    override def unit: Dog = Dog("", 0)

    override def add(x: Dog, y: Dog): Dog = Dog(x.name concat y.name, x.age + y.age)
  }
}


object ImplicitRules {

  def sum[A](xs: List[A])(implicit m: Monoid[A]): A =
    if (xs.isEmpty) m.unit
    else m.add(xs.head, sum(xs.tail))

  def main(args: Array[String]): Unit = {

    //2、如果按照第一条规则没有找到隐式实体的话，那么会在隐式参数的类型(T)的隐式作用域里包含的所有隐式实体中查找
    //2.1、类型T以及它的父类的伴生对象

    //隐式对象

    println(sum(List("a", "b", "c"))) // uses StringMonoid implicitly

    //2.2、参数化类型A的所有的类型参数的伴生对象
    println(sum(List(People("jefft", 30), People("kkk", 22))))

    //2.3、参数化类型A所在的对象

    import Animals.Dog

    println(sum(List(Dog("jefft", 30), Dog("kkk", 22))))

    //2.4、包对象的隐式实体也是被查找的对象
    println(sum(List(1, 3, 4, 1)))

  }

}


